#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <unistd.h>
#include "Thread.hpp"
#include "LockGuard.hpp"
#include "Log.hpp"


const int g_thread_num = 3;


//本质是生产者消费者模型
template <class T>
class ThreadPool
{
public:
    pthread_mutex_t* getMutex()
    {
        return &lock;
    }

    bool isEmpty()
    {
        return _task_queue.empty();
    }

    void waitCond()
    {
        pthread_cond_wait(&cond, &lock);
    }

    T getTask()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }

private:
    ThreadPool(int thread_num = g_thread_num)
        :_num(thread_num)
    {
        for (int i = 1; i <= _num; i++)
        {
            _threads.push_back(new Thread(i, routine, this));
        }
        pthread_mutex_init(&lock, nullptr);
        pthread_cond_init(&cond, nullptr);
    }
    ThreadPool(const ThreadPool<T>& other) = delete;
    const ThreadPool<T>& operator=(const ThreadPool<T>& other) = delete;

public:
    static ThreadPool<T>* getThreadPool(int num = g_thread_num)
    {
        // 可以有效减少未来必定要进行加锁检测的问题
        // 拦截大量的在已经创建好单例的时候，剩余线程请求单例的而直接访问锁的行为
        if (nullptr == thread_ptr)
        {
            LockGuard lockguard(&mutex);
            if (nullptr == thread_ptr)
            {
                thread_ptr = new ThreadPool<T>(num);
            }
        }
        return thread_ptr;
    }


    //1.run
    void run()
    {
        for (auto& iter : _threads)
        {
            iter->start();
            //std::cout << iter->name() << "启动成功" << std::endl;
            logMessage(NORMAL, "%s%s", iter->name().c_str(), "启动成功");
        }
    }

    //线程池本质也是一个生产者消费者模型
    //消费过程
    static void* routine(void* args)
    {
        ThreadData* td = (ThreadData*)args;
        ThreadPool<T>* tp = (ThreadPool<T>*)td->_args;
        while (true)
        {
            T task;
            {
                LockGuard lockguard(tp->getMutex());
                while (tp->isEmpty())
                {
                    tp->waitCond();
                }

                //读取任务
                task = tp->getTask();//任务队列是共享的->将任务从共享拿到自己的私有空间
            }
            task(td->_name);
        }
    }

    //2.pushTask()
    void pushTask(const T& task)
    {
        LockGuard lockguard(&lock);
        _task_queue.push(task);
        pthread_cond_signal(&cond);
    }

    //测试代码
    // void joins()
    // {
    //     for (auto& iter : _threads)
    //     {
    //         iter->join();
    //     }
    // }

    ~ThreadPool()
    {
        for (auto& iter : _threads)
        {
            iter->join();
            delete iter;
        }
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }

private:
    std::vector<Thread*> _threads;
    int _num;
    std::queue<T> _task_queue;

    static ThreadPool<T>* thread_ptr;
    static pthread_mutex_t mutex;

    pthread_mutex_t lock;
    pthread_cond_t cond;
};

template <typename T>
ThreadPool<T>* ThreadPool<T>::thread_ptr = nullptr;

template <typename T>
pthread_mutex_t ThreadPool<T>::mutex = PTHREAD_MUTEX_INITIALIZER;